package keyword_volatile;

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.atomic.AtomicIntegerFieldUpdater;

/**
 * User: ZhangJuntao
 * Date: 14-2-14
 * Time: 上午10:57
 */
//偶数检查
public class EvenChecker implements Runnable {
  static abstract class IntGenerator {
    private volatile boolean canceled = false;

    public abstract int next();

    public void cancel() {
      canceled = true;
    }

    public boolean isCanceled() {
      return canceled;
    }
  }

  static class EvenGenerator extends IntGenerator {
    private int currentEvenValue = 0;
    private final Object lock = new Object();

//  @Override
//  public int next() {
//      ++currentEvenValue;
//      ++currentEvenValue;
//      return currentEvenValue;
//  }

    @Override
    public int next() {
      synchronized (lock) {
        ++currentEvenValue;
        ++currentEvenValue;
        return currentEvenValue;
      }
    }
  }

  static class EvenGenerator2 extends IntGenerator {
    private volatile int currentEvenValue = 0;
    private AtomicIntegerFieldUpdater<EvenGenerator2> updater =
        AtomicIntegerFieldUpdater.newUpdater(EvenGenerator2.class, "currentEvenValue");

    @Override
    public int next() {
      updater.getAndAdd(this, 2);
      return currentEvenValue;//java.util.concurrent.atomic.AtomicLong a = new java.util.concurrent.atomic.AtomicLong();a.addAndGet()
    }
  }

  private IntGenerator generator;
  private final int id;

  public EvenChecker(IntGenerator g, int ident) {
    generator = g;
    id = ident;
  }

  public void run() {
    while (!generator.isCanceled()) {
      int val = generator.next();
      if (val % 2 != 0) {//如果不是偶数
        System.out.println(id + ": " + val + " not even!");
        generator.cancel();
      }
    }
  }


  public static void main(String[] args) {
    ExecutorService exec = Executors.newCachedThreadPool();
    EvenGenerator2 generator = new EvenGenerator2();
    for (int i = 0; i < 3; i++)
      exec.execute(new EvenChecker(generator, i));
    exec.shutdown();
  }
}
